<!DOCTYPE html>
<!--

-->
<html>
<!--
Copyright 2008 The Closure Library Authors. All Rights Reserved.

Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Closure Unit Tests - goog.demos.editor.HelloWorldDialogPlugin</title>
<script src="../../base.js"></script>
<script src="deps.js"></script>
<script>
  goog.require('goog.demos.editor.HelloWorldDialog');
  goog.require('goog.demos.editor.HelloWorldDialog.OkEvent');
  goog.require('goog.demos.editor.HelloWorldDialogPlugin');
  goog.require('goog.demos.editor.HelloWorldDialogPlugin.Command');
  goog.require('goog.dom');
  goog.require('goog.dom.NodeType');
  goog.require('goog.testing.ExpectedFailures');
  goog.require('goog.testing.MockControl');
  goog.require('goog.testing.MockRange');
  goog.require('goog.testing.PropertyReplacer');
  goog.require('goog.testing.editor.FieldMock');
  goog.require('goog.testing.editor.TestHelper');
  goog.require('goog.testing.editor.dom');
  goog.require('goog.testing.events');
  goog.require('goog.testing.jsunit');
  goog.require('goog.testing.mockmatchers.ArgumentMatcher');
  goog.require('goog.userAgent');
</script>
<link rel="stylesheet" href="../css/dialog.css"/>
</head>
<body>

<div id="myField"></div>

<script>

  var plugin;
  var mockCtrl;
  var mockField;
  var mockRange;
  var mockPlaceCursorNextTo;
  var stubs = new goog.testing.PropertyReplacer();

  var fieldObj;

  var CUSTOM_MESSAGE = 'Hello, cruel world...';

  var expectedFailures = new goog.testing.ExpectedFailures();


  function setUp() {
    mockCtrl = new goog.testing.MockControl();

    mockRange = new goog.testing.MockRange();
    mockCtrl.addMock(mockRange);

    mockField =
        new goog.testing.editor.FieldMock(undefined, undefined, mockRange);
    mockCtrl.addMock(mockField);

    mockPlaceCursorNextTo = mockCtrl.createFunctionMock('placeCursorNextTo');
  }

  function tearDown() {
    plugin.dispose();
    tearDownRealEditableField();
    expectedFailures.handleTearDown();
    stubs.reset();
    goog.dom.getElement('myField').innerHTML = '';
  }

  /**
   * Tests that the plugin's dialog is properly created.
   */
  function testCreateDialog() {
    mockField.$replay();

    plugin = new goog.demos.editor.HelloWorldDialogPlugin();
    plugin.registerFieldObject(mockField);

    var dialog = plugin.createDialog(goog.dom.getDomHelper());
    assertTrue('Dialog should be of type goog.demos.editor.HelloWorldDialog',
               dialog instanceof goog.demos.editor.HelloWorldDialog);

    mockField.$verify();
  }

  /**
   * Tests that when the OK event fires the editable field is properly updated.
   */
  function testOk() {
    mockField.focus();
    mockField.dispatchBeforeChange();
    mockRange.removeContents();
    // Tests that an argument is a span with the custom message.
    var createdNodeMatcher = new goog.testing.mockmatchers.ArgumentMatcher(
        function(arg) {
          return arg.nodeType == goog.dom.NodeType.ELEMENT &&
                 arg.tagName == goog.dom.TagName.SPAN &&
                 goog.dom.getRawTextContent(arg) == CUSTOM_MESSAGE;
        });
    mockRange.insertNode(createdNodeMatcher, false);
    mockRange.$does(function(node, before) {
      return node;
    });
    mockPlaceCursorNextTo(createdNodeMatcher, false);
    stubs.set(goog.editor.range, 'placeCursorNextTo', mockPlaceCursorNextTo);
    mockField.dispatchSelectionChangeEvent();
    mockField.dispatchChange();
    mockCtrl.$replayAll();

    plugin = new goog.demos.editor.HelloWorldDialogPlugin();
    plugin.registerFieldObject(mockField);
    var dialog = plugin.createDialog(goog.dom.getDomHelper());

    // Mock of execCommand + clicking OK without actually opening the dialog.
    dialog.dispatchEvent(
        new goog.demos.editor.HelloWorldDialog.OkEvent(CUSTOM_MESSAGE));

    mockCtrl.$verifyAll();
  }

  /**
   * Setup a real editable field (instead of a mock) and register the plugin to
   * it.
   */
  function setUpRealEditableField() {
    fieldObj = new goog.editor.Field('myField', document);
    fieldObj.makeEditable();
    // Register the plugin to that field.
    plugin = new goog.demos.editor.HelloWorldDialogPlugin();
    fieldObj.registerPlugin(plugin);
  }

  /**
   * Tear down the real editable field.
   */
  function tearDownRealEditableField() {
    if (fieldObj) {
      fieldObj.makeUneditable();
      fieldObj.dispose();
    }
  }

  /**
   * Tests that the selection is cleared when the dialog opens and is
   * correctly restored after ok is clicked.
   */
  function testRestoreSelectionOnOk() {
    setUpRealEditableField();

    fieldObj.setHtml(false, '12345');
    var elem = fieldObj.getElement();
    var helper = new goog.testing.editor.TestHelper(elem);
    helper.select('12345', 1, '12345', 4); // Selects '234'.

    assertEquals('Incorrect text selected before dialog is opened',
                 '234',
                 fieldObj.getRange().getText());
    plugin.execCommand(
        goog.demos.editor.HelloWorldDialogPlugin.Command.HELLO_WORLD_DIALOG);

    // TODO(user): IE returns some bogus range when field doesn't have
    // selection. Remove the expectedFailure when robbyw fixes the issue.
    // NOTE(user): You can't remove the selection from a field in Opera without
    // blurring it.
    elem.parentNode.blur();
    expectedFailures.expectFailureFor(goog.userAgent.IE ||
                                      goog.userAgent.OPERA);
    try {
      assertNull('There should be no selection while dialog is open',
                 fieldObj.getRange());
    } catch (e) {
      expectedFailures.handleException(e);
    }

    goog.testing.events.fireClickSequence(
        plugin.dialog_.getOkButtonElement());
    assertEquals('No text should be selected after clicking ok',
                 '',
                 fieldObj.getRange().getText());

    // Test that the caret is placed after the custom message.
    goog.testing.editor.dom.assertRangeBetweenText(
        'Hello, world!', '5', fieldObj.getRange());
  }


</script>
</body>
</html>
